﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.AddIn;
using RootfusAddinView;
using System.Windows;

namespace ROOTObjectAddins
{
    /// <summary>
    /// An addin that will do division of two histograms.
    /// </summary>
    [AddIn("LaTeX Box", Description = "Output pin is a TLatex useful for displaying on a histogram or similar")]
    public class TText : RootfusSurfaceItem
    {
        public TText()
        {
            _root_text = _cached_state._text;
            _xloc = _cached_state._xloc;
            _yloc = _cached_state._yloc;
            _font = _cached_state._font;
        }

        /// <summary>
        /// The text we will display!
        /// </summary>
        private string _root_text;
        public string RootText
        {
            get { return _root_text; }
            set
            {
                _root_text = value;
                if (_ui_norm != null)
                {
                    _ui_norm.lbText.Content = value;
                }
                Update();
            }
        }

        /// <summary>
        /// Private cache of the x and y location -- don't read/write to here!
        /// </summary>
        private double _xloc = 0.0;
        private double _yloc = 0.0;

        /// <summary>
        /// Get/set the x location of our text. Changing this will alter the location!
        /// </summary>
        public double XLoc
        {
            get { return _xloc; }
            set
            {
                _xloc = value;
                Update();
            }
        }

        /// <summary>
        /// Get/Set the ylocation of the time. Changing this will alter out output!
        /// </summary>
        public double YLoc
        {
            get { return _yloc; }
            set
            {
                _yloc = value;
                Update();
            }
        }

        private short _font;

        public short Font
        {
            get { return _font; }
            set
            {
                _font = value;
                Update();
            }
        }


        /// <summary>
        /// Holds a cache of our state.
        /// </summary>
        public class OurState
        {
            public string _text = "Some Text";
            public double _xloc = 0.1;
            public double _yloc = 0.1;
            public short _font = 72;
        }

        private OurState _cached_state = new OurState();

        private void CacheState()
        {
            _cached_state._text = RootText;
            _cached_state._xloc = XLoc;
            _cached_state._yloc = YLoc;
            _cached_state._font = _font;
        }
        private void UnCacheState(OurState s)
        {
            RootText = s._text;
            XLoc = _cached_state._xloc;
            YLoc = _cached_state._yloc;
            Font = _cached_state._font;
        }

        private bool StateDifferentFromCache()
        {
            return _cached_state._text != RootText
                || _cached_state._yloc != YLoc
                || _cached_state._xloc != XLoc
                || _cached_state._font != _font;
        }

        /// <summary>
        /// Cache the local copy of the user interface. Best to
        /// reference SurfaceUI property as that will make sure
        /// it is created.
        /// </summary>
        private TTextUINormal _ui_norm = null;

        /// <summary>
        /// Returns the normal UI. Only create one per addin instance! If you get asked
        /// for it multiple times return the same one!
        /// </summary>
        public override System.Windows.FrameworkElement SurfaceUI
        {
            get
            {
                if (_ui_norm == null)
                {
                    _ui_norm = new TTextUINormal();
                    _ui_norm.lbText.Content = RootText;
                }
                return _ui_norm;
            }
        }

        /// <summary>
        /// Return the config UI. Return a new one each time, or keep
        /// track -- whatever is simpler.
        /// </summary>
        public override System.Windows.FrameworkElement ConfigUI
        {
            get
            {
                TTextUIConfig ui = new TTextUIConfig();
                ui.DataContext = this;
                CacheState();
                return ui;
            }
        }

        /// <summary>
        /// The config has closed. See if our options changed. If so, update things!
        /// </summary>
        public override void ConfigDone()
        {
            if (StateDifferentFromCache())
            {
                CacheState();
                Callback.UpdateSaveObject(_cached_state);
                Update();
            }
        }

        /// <summary>
        /// Our settings are getting set, externally.
        /// </summary>
        /// <param name="xml_config"></param>
        public override void SetConfigXML(string xml_config)
        {
            _cached_state = Callback.ConvertXMLToSettings<OurState>(xml_config);
            UnCacheState(_cached_state);
        }

        /// <summary>
        /// If you don't need a config -- then get rid fo the ConfigUI and change the
        /// return to false.
        /// </summary>
        public override bool HasSettingsUI
        {
            get { return true; }
        }

        /// <summary>
        /// We have only a single output pin -- the text we are showing!
        /// </summary>
        private List<string> _output_pins_names = new List<string>() {"Text"};

        /// <summary>
        /// Names of all our output pins
        /// </summary>
        public override IList<string> OutputPinNames
        {
            get { return _output_pins_names; }
        }

        /// <summary>
        /// Return the actual text block.
        /// </summary>
        /// <param name="pin"></param>
        /// <returns></returns>
        public override ROOTNET.Interface.NTObject GetPinDataAsTObject(string pin)
        {
            if (pin == _output_pins_names[0])
            {
                return _root_text_block;
            }
            return null;
        }

        /// <summary>
        /// No input pins, but we have to report that...
        /// </summary>
        private List<PinDefinition> _input_pins = new List<PinDefinition>();

        public override IList<PinDefinition> InputPins
        {
            get { return _input_pins; }
        }

        /// Store the text box result so people can get at it!
        ROOTNET.NTLatex _root_text_block = null;

        /// <summary>
        /// We have no inputs, so it is odd to get this call! But we will
        /// re-gen the text box anyway just in case! We also get called
        /// when something about our inputes is changed. So that makes sense
        /// that we would do something here!
        /// </summary>
        public override void Update()
        {
            _root_text_block = new ROOTNET.NTLatex(XLoc, YLoc, RootText);
            _root_text_block.SetNDC();
            _root_text_block.SetTextFont(_font);
            Callback.OutputPinsChanged();
        }
    }
}
